#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@file monitoring_service.py
@brief 监控业务服务类
@details 提供状态监控和数据记录业务逻辑
@author Motor Controller Team
@date 2024
"""

import logging
import threading
import time
from typing import Optional, Callable, Dict, Any
from queue import Queue, Empty

from business.motor_service import MotorService
from core.config import ConfigManager

logger = logging.getLogger(__name__)


class MonitoringService:
    """
    @brief 监控业务服务类
    @details 提供状态监控和数据记录业务逻辑
    """
    
    def __init__(self, motor_service: MotorService, config_manager: ConfigManager):
        """
        @brief 初始化监控服务
        @param motor_service 电机服务
        @param config_manager 配置管理器
        """
        self.motor_service = motor_service
        self.config_manager = config_manager
        
        # 监控状态
        self.monitoring = False
        self.monitor_thread: Optional[threading.Thread] = None
        self.monitoring_interval = 0.1
        
        # 数据记录状态
        self.logging = False
        self.log_thread: Optional[threading.Thread] = None
        self.log_queue = Queue()
        self.log_file = "motor_data.log"
        
        # 状态历史记录
        self.status_history: list = []
        self.max_history_size = 1000
        
        # 回调函数
        self.status_callback: Optional[Callable] = None
        self.error_callback: Optional[Callable] = None
        
        logger.info("监控服务初始化完成")
    
    def set_status_callback(self, callback: Callable) -> None:
        """
        @brief 设置状态回调
        @param callback 回调函数
        """
        self.status_callback = callback
    
    def set_error_callback(self, callback: Callable) -> None:
        """
        @brief 设置错误回调
        @param callback 回调函数
        """
        self.error_callback = callback
    
    def start_monitoring(self) -> bool:
        """
        @brief 开始状态监控
        @return bool 启动是否成功
        """
        if self.monitoring:
            logger.warning("监控已在运行中")
            return False
        
        if not self.motor_service.is_connected():
            error_msg = "电机服务未连接，无法开始监控"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
        
        try:
            # 获取监控间隔配置
            ui_config = self.config_manager.get_ui_config()
            self.monitoring_interval = ui_config.monitoring_interval
            
            self.monitoring = True
            self.monitor_thread = threading.Thread(
                target=self._monitoring_loop,
                daemon=True
            )
            self.monitor_thread.start()
            
            logger.info("状态监控已启动")
            return True
            
        except Exception as e:
            self.monitoring = False
            error_msg = f"启动监控异常: {e}"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
    
    def stop_monitoring(self) -> None:
        """
        @brief 停止状态监控
        """
        if not self.monitoring:
            return
        
        self.monitoring = False
        if self.monitor_thread:
            self.monitor_thread.join(timeout=2.0)
        
        logger.info("状态监控已停止")
    
    def start_logging(self, log_file: str = None) -> bool:
        """
        @brief 开始数据记录
        @param log_file 日志文件路径
        @return bool 启动是否成功
        """
        if self.logging:
            logger.warning("数据记录已在运行中")
            return False
        
        try:
            if log_file:
                self.log_file = log_file
            
            self.logging = True
            self.log_thread = threading.Thread(
                target=self._logging_loop,
                daemon=True
            )
            self.log_thread.start()
            
            logger.info(f"数据记录已启动，日志文件: {self.log_file}")
            return True
            
        except Exception as e:
            self.logging = False
            error_msg = f"启动数据记录异常: {e}"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return False
    
    def stop_logging(self) -> None:
        """
        @brief 停止数据记录
        """
        if not self.logging:
            return
        
        self.logging = False
        if self.log_thread:
            self.log_thread.join(timeout=2.0)
        
        logger.info("数据记录已停止")
    
    def log_data(self, data: Dict[str, Any]) -> None:
        """
        @brief 记录数据
        @param data 要记录的数据
        """
        if self.logging:
            self.log_queue.put(data)
    
    def get_status_history(self, count: Optional[int] = None) -> list:
        """
        @brief 获取状态历史记录
        @param count 要获取的记录数量
        @return list 状态历史记录列表
        """
        if count is None:
            return self.status_history.copy()
        else:
            return self.status_history[-count:] if count > 0 else []
    
    def clear_status_history(self) -> None:
        """
        @brief 清空状态历史记录
        """
        self.status_history.clear()
        logger.info("状态历史记录已清空")
    
    def get_latest_status(self) -> Optional[Dict[str, Any]]:
        """
        @brief 获取最新状态
        @return Optional[Dict[str, Any]] 最新状态信息
        """
        if self.status_history:
            return self.status_history[-1]
        return None
    
    def is_monitoring(self) -> bool:
        """
        @brief 检查是否正在监控
        @return bool 是否正在监控
        """
        return self.monitoring
    
    def is_logging(self) -> bool:
        """
        @brief 检查是否正在记录
        @return bool 是否正在记录
        """
        return self.logging
    
    def _monitoring_loop(self) -> None:
        """
        @brief 监控循环
        @details 在独立线程中运行，定期读取电机状态
        """
        logger.info("监控循环开始")
        
        while self.monitoring:
            try:
                # 获取电机状态
                status = self.motor_service.get_motor_status()
                if status:
                    # 添加到历史记录
                    self._add_to_history(status)
                    
                    # 检测异常
                    self._check_for_errors(status)
                    
                    # 记录数据
                    if self.logging:
                        self.log_data(status)
                    
                    # 调用状态回调
                    if self.status_callback:
                        try:
                            self.status_callback(status)
                        except Exception as e:
                            logger.error(f"状态回调函数执行错误: {e}")
                
                # 等待下次监控
                time.sleep(self.monitoring_interval)
                
            except Exception as e:
                logger.error(f"监控循环中发生错误: {e}")
                if self.error_callback:
                    try:
                        self.error_callback(e)
                    except Exception as callback_error:
                        logger.error(f"错误回调函数执行错误: {callback_error}")
                
                # 发生错误时稍微延长等待时间
                time.sleep(self.monitoring_interval * 2)
        
        logger.info("监控循环结束")
    
    def _logging_loop(self) -> None:
        """
        @brief 记录循环
        @details 在独立线程中运行，将数据写入文件
        """
        logger.info("数据记录循环开始")
        
        try:
            with open(self.log_file, 'a', encoding='utf-8') as f:
                while self.logging:
                    try:
                        # 从队列获取数据
                        data = self.log_queue.get(timeout=1.0)
                        
                        # 写入文件
                        timestamp = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
                        log_line = f"{timestamp} - {data}\n"
                        f.write(log_line)
                        f.flush()
                        
                    except Empty:
                        # 队列为空，继续等待
                        continue
                    except Exception as e:
                        logger.error(f"写入日志文件时发生错误: {e}")
                        
        except Exception as e:
            logger.error(f"数据记录循环中发生错误: {e}")
        
        logger.info("数据记录循环结束")
    
    def _add_to_history(self, status: Dict[str, Any]) -> None:
        """
        @brief 添加状态到历史记录
        @param status 状态信息
        """
        self.status_history.append(status)
        
        # 限制历史记录大小
        if len(self.status_history) > self.max_history_size:
            self.status_history.pop(0)
    
    def _check_for_errors(self, status: Dict[str, Any]) -> None:
        """
        @brief 检查状态中的错误
        @param status 状态信息
        """
        # 检查错误代码
        error_code = status.get('error_code')
        if error_code is not None and error_code != 0:
            error_msg = f"检测到错误代码: {error_code}"
            logger.warning(error_msg)
            
            if self.error_callback:
                try:
                    self.error_callback({
                        'type': 'error_code',
                        'code': error_code,
                        'message': error_msg,
                        'timestamp': time.time()
                    })
                except Exception as e:
                    logger.error(f"错误回调函数执行错误: {e}")
        
        # 检查电机状态
        left_state = status.get('left_motor_state')
        right_state = status.get('right_motor_state')
        
        if left_state == 'fault' or right_state == 'fault':
            error_msg = f"检测到电机故障 - 左电机: {left_state}, 右电机: {right_state}"
            logger.warning(error_msg)
            
            if self.error_callback:
                try:
                    self.error_callback({
                        'type': 'motor_fault',
                        'left_motor': left_state,
                        'right_motor': right_state,
                        'timestamp': time.time()
                    })
                except Exception as e:
                    logger.error(f"错误回调函数执行错误: {e}")
